{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The Box widgets\n",
    "\n",
    "+ Box\n",
    "+ FlexBox\n",
    "+ Accordion\n",
    "+ TabWidget"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "These widgets are used to provide a layout for placing other widgets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "{-# LANGUAGE OverloadedStrings #-}\n",
    "import IHaskell.Display.Widgets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These widgets have a `Children` field, which accepts a `[ChildWidget]`. A `ChildWidget` can be created using the `ChildWidget` constructor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    ":t ChildWidget"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### `Box` and `FlexBox`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "-- Create new Box and FlexBox\n",
    "box <- mkBox\n",
    "flx <- mkFlexBox"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By default, boxes have a horizontal orientation. Thus adding some widgets to them lays them out horizontally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import Control.Monad (replicateM)\n",
    "\n",
    "-- Make some buttons\n",
    "buttons <- replicateM 20 mkButton\n",
    "\n",
    "-- Add children widgets to boxes\n",
    "let children = map ChildWidget buttons\n",
    "setField box Children children\n",
    "setField flx Children children\n",
    "\n",
    "-- Display boxes\n",
    "box\n",
    "flx"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You might be thinking that there is no difference between `Box` and `FlexBox`, but that's not true.\n",
    "\n",
    "Following are some differences:\n",
    "\n",
    "+ `Box` is always horizontal, whereas `FlexBox` has a configurable `Orientation`.\n",
    "+ `FlexBox` is flexible, and the flexibility is determined by its `Flex` field (0 to 2).\n",
    "+ `FlexBox` also has explicit `Pack` and `Align` fields.\n",
    "\n",
    "Let's see these differences in action:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "-- Trying to set orientation for Boxes\n",
    "setField box Orientation VerticalOrientation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The error means that the widget doesn't possess the `Orientation` property."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "-- Trying to set orientation for FlexBox\n",
    "setField flx Orientation VerticalOrientation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ProxyWidget and PlaceProxy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `ProxyWidget` widget allows for zero-or-one widgets to be placed inside it.\n",
    "\n",
    "From the IHaskell perspective, this is similar to the `Output` widget, but supports only widgets inside it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "[b1, b2, b3] <- replicateM 3 mkButton\n",
    "\n",
    "setField b1 Description \"Button 1\"\n",
    "setField b2 Description \"Button 2\"\n",
    "setField b3 Description \"Button 3\"\n",
    "\n",
    "-- A proxy widget to display one button at a time\n",
    "proxy <- mkProxyWidget\n",
    "\n",
    "-- b1 ~> b2\n",
    "setField b1 ClickHandler $ setField proxy Child (Just $ ChildWidget b2)\n",
    "\n",
    "-- b2 ~> b3\n",
    "setField b2 ClickHandler $ setField proxy Child (Just $ ChildWidget b3)\n",
    "\n",
    "-- b3 ~> b1\n",
    "setField b3 ClickHandler $ setField proxy Child (Just $ ChildWidget b1)\n",
    "\n",
    "-- Set initial child, and display\n",
    "setField proxy Child (Just $ ChildWidget b1)\n",
    "\n",
    "proxy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `PlaceProxy` widget allows for more flexible use-cases involving arbitrary widgets. It is similar to `ProxyWidget`, but allows more control over where the widget is displayed.\n",
    "\n",
    "This widget can be used to display widgets inside markdown cells, among other places such as custom widgets or custom html elements. For example, we can create a html `div` inside this markdown cell, and cause the child widget to display in it using its CSS selector.\n",
    "\n",
    "`<div id=\"widget_out\"></div>`\n",
    "\n",
    "<div id=\"widget_out\"></div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "pp <- mkPlaceProxy\n",
    "button <- mkButton\n",
    "setField button Description \"(0,0)\"\n",
    "\n",
    "-- Put button inside the place proxy widget\n",
    "setField pp Child (Just $ ChildWidget button)\n",
    "\n",
    "-- Output to the div created above\n",
    "setField pp Selector \"#widget_out\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The widget doesn't yet display, but when we try to display it, the child widget shows in the div as expected."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "pp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### `Accordion` and `TabWidget`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These widgets are useful for displaying a variety of content in a small amount of space."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "acc <- mkAccordion\n",
    "tab <- mkTabWidget"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's add some children and see what the result looks like."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "buttons' <- replicateM 5 mkButton\n",
    "\n",
    "let children = map ChildWidget buttons'\n",
    "\n",
    "setField acc Children children\n",
    "setField tab Children children\n",
    "\n",
    "acc\n",
    "tab"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Both the widgets are similar, the only major difference is in the orientation. `Accordion` is vertical, whereas `TabWidget` is horizontal."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Haskell",
   "language": "haskell",
   "name": "haskell"
  },
  "language_info": {
   "codemirror_mode": "ihaskell",
   "file_extension": ".hs",
   "name": "haskell",
   "version": "7.10.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
